package com.gxa.common.handler;


import com.fasterxml.jackson.databind.exc.InvalidDefinitionException;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
import com.gxa.common.R;
import com.gxa.common.exception.HeaderParamFormatException;
import com.gxa.common.exception.UnExceptFileUploadException;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import javax.naming.SizeLimitExceededException;

/**
 * @author MacieSerenity
 */
@ControllerAdvice
public class CommonExceptionHandler {

    /**
     * 统一异常处理，处理数据绑定时出现的数据转换异常</br>
     * 例如：预期接收Integer 但是收到String
     *
     * @param e 错误的信息
     * @return 拦截后返回的R对象
     */
    @ExceptionHandler({InvalidFormatException.class})
    @ResponseBody
    public R invalidFormatExceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(400);
        result.setMsg("Jackson反序列化错误！可能原因：" +
                "你传输的数据在后端接收后发生了数据转换异常，" +
                "请注意你传输的数据类型是否与后端接口匹配！详细信息：" + e.getMessage());
        return result;
    }

    /**
     * 统一异常处理，处理数据绑定时出现的数据转换异常</br>
     * 例如：预期接收Integer 但是收到String
     *
     * @param e 错误的信息
     * @return 拦截后返回的R对象
     */
    @ExceptionHandler({MethodArgumentTypeMismatchException.class})
    @ResponseBody
    public R methodArgumentTypeMismatchExceptionExceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(400);
        result.setMsg("方法参数类型不匹配，可能原因：你没有提供后端需要的某些必须的参数等，" +
                "请注意你传输的数据类型是否与后端接口匹配！详细信息：" + e.getMessage());
        return result;
    }

    /**
     * 统一异常处理，处理数据绑定时出现的数据转换异常</br>
     * 例如：预期接收Integer 但是收到String
     *
     * @param e 错误的信息
     * @return 拦截后返回的R对象
     */
    @ExceptionHandler({MismatchedInputException.class})
    @ResponseBody
    public R mismatchedInputExceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(400);
        result.setMsg("不匹配的输入异常，可能原因：数据格式错误，" +
                "请注意输入的数据格式，个数等是否正确，请检查后传入正确的参数。" +
                "详细信息：" + e.getMessage());
        return result;
    }

    /**
     * 统一异常处理，处理数据绑定时出现的数据转换异常</br>
     * 例如：预期接收Integer 但是收到String
     *
     * @param e 错误的信息
     * @return 拦截后返回的R对象
     */
    @ExceptionHandler({MissingServletRequestParameterException.class})
    @ResponseBody
    public R missingServletRequestParameterExceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(400);
        result.setMsg("缺少Servlet请求参数异常！，请注意输入的数据格式，个数等是否正确，请检查后传入正确的参数。" +
                "具体信息：" + e.getMessage());
        return result;
    }

    /**
     * 统一异常处理，处理数据绑定时出现的数据转换异常</br>
     * 例如：预期接收Integer 但是收到String
     *
     * @param e 错误的信息
     * @return 拦截后返回的R对象
     */
    @ExceptionHandler({HttpRequestMethodNotSupportedException.class})
    @ResponseBody
    public R httpRequestMethodNotSupportedExceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(405);
        result.setMsg("请求的方法不匹配！请检查前后端的请求方式是否相同，" +
                "可能的原因：把GET请求写成了POST请求等，请检查后传入正确的参数。" +
                "具体信息：" + e.getMessage());
        return result;
    }

    /**
     * 统一异常处理，处理数据绑定时出现的数据转换异常</br>
     * 例如：预期接收Integer 但是收到String
     *
     * @param e 错误的信息
     * @return 拦截后返回的R对象
     */
    @ExceptionHandler({HttpMediaTypeNotSupportedException.class})
    @ResponseBody
    public R httpMediaTypeNotSupportedExceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(500);
        result.setMsg("请注意你的请求格式是否是JSON，好像格式不太对，确认是application/xml;charset=UTF-8吗？！" +
                "具体信息：" + e.getMessage());
        return result;
    }
    /**
     * 统一异常处理，处理数据绑定时出现的数据转换异常</br>
     * 例如：预期接收Integer 但是收到String
     *
     * @param e 错误的信息
     * @return 拦截后返回的R对象
     */
    @ExceptionHandler({HttpMessageNotReadableException.class})
    @ResponseBody
    public R httpMessageNotReadableExceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(500);
        result.setMsg("请注意你的请求格式是否是JSON，请不要在加了@RequestBody的方法后使用普通传参的方式！请在raw中选择json方式传输！" +
                "具体信息：" + e.getMessage());
        return result;
    }


    /**
     * 统一异常处理，处理数据绑定时出现的数据转换异常</br>
     * 例如：预期接收Integer 但是收到String
     *
     * @param e 错误的信息
     * @return 拦截后返回的R对象
     */
    @ExceptionHandler({InvalidDefinitionException.class})
    @ResponseBody
    public R invalidDefinitionExceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(500);
        result.setMsg("发生错误！可能原因：需要在报错的实体类（注意是实体类）上方添加@JsonIgnoreProperties(value={\"hibernateLazyInitializer\",\"handler\",\"fieldHandler\"})注解" +
                "具体信息：" + e.getMessage());
        return result;
    }


    static final Integer MAX_FILE_SIZE_MB = 1;

    /**
     * 文件大小超出异常
     *
     * @param e 错误的信息
     * @return 拦截后返回的R对象
     */
    @ExceptionHandler({SizeLimitExceededException.class})
    @ResponseBody
    public R sizeLimitExceededExceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(500);
        result.setMsg("(＾Ｕ＾)ノ~ＹＯ 上传的头像文件大小过大捏，请将文件压缩或者换一个文件捏，当前最大大小：" + MAX_FILE_SIZE_MB + "MB，具体信息：" + e.getMessage());
        return result;
    }

    /**
     * 请求头参数异常
     *
     * @param e 异常信息
     * @return R
     */
    @ExceptionHandler({HeaderParamFormatException.class})
    @ResponseBody
    public R headerParamFormatExceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(500);
        result.setMsg("缺少请求头参数，看看你是不是少了Header里的userID这个参数，记得要传userID哦，啾咪❤❤❤❤❤❤❤❤❤" +
                "具体信息：" + e.getMessage());
        return result;
    }

    @ExceptionHandler({UnExceptFileUploadException.class})
    @ResponseBody
    public R unExceptFileUploadExceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(500);
        result.setMsg("文件上传异常！" +
                "具体信息：" + e.getMessage());
        return result;
    }
    @ExceptionHandler({UnauthorizedException.class})
    @ResponseBody
    public R unauthorizedExceptionHandler(Exception e){
        e.printStackTrace();
        R result = new R();
        result.setCode(500);
        result.setMsg("没有该权限！！" +
                "具体信息：" + e.getMessage());
        return result;
    }

    /**
     * 统一异常处理，处理数据绑定时出现的数据转换异常</br>
     * 例如：预期接收Integer 但是收到String
     *
     * @param e 错误的信息
     * @return 拦截后返回的R对象
     */
    @ExceptionHandler({Exception.class})
    @ResponseBody
    public R exceptionHandler(Exception e) {
        e.printStackTrace();
        R result = new R();
        result.setCode(500);
        result.setMsg("❤激❤情❤代❤码❤未❤知❤异❤常❤！❤" +
                "具体信息：" + e.getMessage());
        return result;
    }



}
